#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;

void dfs(const vector<vector<int>>& graph, vector<bool>& visited, int node) {
    visited[node] = true;
    for (int i = 0; i < graph[node].size(); ++i) {
        if (graph[node][i] == 1 && !visited[i]) {
            dfs(graph, visited, i);
        }
    }
}

int nucleic_acid_testing(const vector<vector<int>>& graph, const unordered_set<int>& confirmed_cases) {
    int n = graph.size();
    vector<bool> visited(n, false);

    for (int case_num : confirmed_cases) {
        dfs(graph, visited, case_num);
    }

    // 计算需要进行核酸检测的人数
    int testing_count = 0;
    for (bool v : visited) {
        if (v) {
            testing_count++;
        }
    }

    testing_count -= confirmed_cases.size(); // 减去确诊病例的数量

    return testing_count;
}

int main() {
    int n;
    cin >> n;
    string str;
    cin >> str;
    unordered_set<int> confirmed;
    string temp = "";
    for (int i = 0; i < str.size(); i++) {
        if (str[i] == ',') {
            confirmed.insert(stoi(temp));
            temp = "";
        } else {
            temp += str[i];
        }
    }
    confirmed.insert(stoi(temp));
    vector<vector<int>> contact(n, vector<int>(n, 0));
    for (int i = 0; i < n; i++) {
        string str;
        cin >> str;
        string temp = "";
        for (int j = 0; j < str.size(); j++) {
            if (str[j] != ',') {
                temp += str[j];
            }
        }
        for(int j = 0; j < n; j++){
            contact[i][j] = temp[j] - '0';
        }
    }
    for(auto i : confirmed){
        cout << i << " ";
    }
    cout << endl;
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            cout << contact[i][j] << " ";
        }
        cout << endl;
    }
    cout << nucleic_acid_testing(contact, confirmed) << endl;
    return 0;
}

// #include <iostream>
// #include <vector>
// #include <sstream>

// using namespace std;

// class UnionFind {
// public:
//     vector<int> father;

//     UnionFind(int len) {
//         father.resize(len + 1);
//         for (int i = 0; i <= len; i++) {
//             father[i] = i;
//         }
//     }

//     int find(int x) {
//         if (x < 0 || x >= father.size()) {
//             throw out_of_range("查询越界");
//         }

//         return (x == father[x] ? x : (father[x] = find(father[x])));
//     }

//     void merge(int x, int y) {
//         int xRoot = find(x), yRoot = find(y);
//         father[yRoot] = xRoot;
//     }
// };

// int main() {
//     int n;
//     cin >> n;
//     cin.ignore();  // 消耗掉换行符

//     string confirmInput;
//     getline(cin, confirmInput);

//     stringstream confirmStream(confirmInput);
//     vector<int> confirm;
//     int confirmNum;
//     while (confirmStream >> confirmNum) {
//         confirm.push_back(confirmNum);
//         if (confirmStream.peek() == ',') {
//             confirmStream.ignore();
//         }
//     }

//     int start = confirm[0];
//     UnionFind uf(n);

//     for (size_t i = 1; i < confirm.size(); i++) {
//         uf.merge(start, confirm[i]);
//     }

//     for (int i = 0; i < n; i++) {
//         string rowInput;
//         getline(cin, rowInput);

//         stringstream rowStream(rowInput);
//         int contact;
//         for (int j = 0; j < n; j++) {
//             rowStream >> contact;
//             if (contact == 1) {
//                 uf.merge(i, j);
//             }
//             if (rowStream.peek() == ',') {
//                 rowStream.ignore();
//             }
//         }
//     }

//     int cnt = 0;
//     for (int i = 0; i < n; i++) {
//         if (uf.find(i) == uf.find(start)) {
//             cnt++;
//         }
//     }

//     cout << cnt - confirm.size() << endl;

//     return 0;
// }

